//
//  AudioRecorder.m
//  Huahai
//
//  Created by Fox Guo on 13-8-12.
//
//

#import "AudioRecorder.h"
#import "HOUtils.h"
#import "VoiceConverter.h"
#include "amrFileCodec.h"
#import "Logger.h"
#import "HODefine.h"
#import "HOAlertView.h"
#import "HOConstants.h"

@implementation HOAVAudioRecorder
@synthesize filePath = _filePath;
@synthesize fileName = _fileName;
@synthesize wavfilePath = _wavfilePath;
- (id)init
{
	if(self = [super init])
	{
		_filePath = nil;
		_fileName = nil;
		_wavfilePath = nil;
	}
	return self;
}
- (void)dealloc
{
	
	_fileName = nil;
	_filePath = nil;
	_wavfilePath = nil;
	[super dealloc];
}

@end
#pragma mark
#pragma mark --


@implementation AudioRecorder


- (id)initWithDelegate:(id<AudioRecordDelegate>)delgate
{
    if(self = [super init])
    {
        _delgate = delgate;
        avRecorder = nil;
        session = [AVAudioSession sharedInstance];
    }
    return self;
}
- (BOOL)checkHardwarePass
{
    
    NSError *err = nil;
    session = [AVAudioSession sharedInstance];
    [session setCategory: AVAudioSessionCategoryPlayAndRecord error: &err];
    if(err){
        LogNor(@"audioSession: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
        [_delgate onErrorArise:err];
        
        return NO;
    }
    [session setActive:YES error:&err];
    err = nil;
    if(err){
        LogNor(@"audioSession: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
        [_delgate onErrorArise:err];
        return NO;
    }
    [session setActive:YES error:&err];
    if(err){
        LogNor(@"audioSession: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
        [_delgate onErrorArise:err];
        return NO;
    }
    
    BOOL audioHWAvailable = session.inputIsAvailable;
    if (! audioHWAvailable) {
        HOAlertView *cantRecordAlert =
        [[HOAlertView alloc] initWithTitle: @"警告"
                                   message: @"语音输出设备无效，请检查！"
                                  delegate: nil
                         cancelButtonTitle:@"关闭"
                         otherButtonTitles:nil];
		
		cantRecordAlert.tag = [kHO_DIALOG_AudioDeviceWarning integerValue];
        [cantRecordAlert show];
		[cantRecordAlert release];
        return NO;
    }
    else
    {
        return YES;
    }
    
}

- (void)startRecordTimer
{
    // return;
    NSTimeInterval interval = isRecordLessOnSecTimeout ? TIMEOUT_RECORD_LESS_ONE_SECOND : REPEAT_DETECTING_VOICE;
    if(recordingTimer == nil)
    {
        recordingTimer = [NSTimer scheduledTimerWithTimeInterval: interval
                                                          target: self
                                                        selector: @selector(handleRecordingTimer:)
                                                        userInfo: nil
                                                         repeats: YES];
    }
    if(isRecordLessOnSecTimeout)
    {
        [_delgate onRecordLessOneSecond:YES];
    }
}
- (void)stopTimer
{
    [recordingTimer invalidate];
    recordingTimer = nil;
}
- (void)handleRecordingTimer:(NSTimer *)timer
{
    if(isRecordLessOnSecTimeout)
    {
        [_delgate onRecordLessOneSecond:NO];
        isRecordLessOnSecTimeout = NO;
        [self stopTimer];
    }
    else
    {
        [avRecorder updateMeters];
        double lowPassResults = pow(10, (0.05 * [avRecorder peakPowerForChannel:0]));
//        LogNor(@"[avRecorder peakPowerForChannel:0] %lf",[avRecorder peakPowerForChannel:0]);
        if(avRecorder.isRecording)
        {
            recordTime = avRecorder.currentTime;
//            LogNor(@"recordTime:%.1f", recordTime);
            if (recordTime > NOTICE_RECORDING_TIME && recordTime < MAX_RECORDING_TIME)
            {
                [_delgate showNotificationForRecordTime:recordTime];
            }
            if (recordTime >= MAX_RECORDING_TIME) {
				
                [_delgate onRecordMoreThanOneMinute];
               

            }
        }
        [_delgate onDetectingVoice:lowPassResults];
    }
}
- (void)initRecord
{
    if(![self checkHardwarePass])
        return;
    [self destoryRecord:NO];
    NSError *err = nil;
//    kAudioFormatAppleIMA4
    NSDictionary *recordSettings = [NSDictionary
                                    dictionaryWithObjectsAndKeys:
                                    [NSNumber numberWithInt:AVAudioQualityHigh],
                                    AVEncoderAudioQualityKey,
                                    [NSNumber numberWithInt: 1],
                                    AVNumberOfChannelsKey,
                                    [NSNumber numberWithFloat:8000.0],
                                    AVSampleRateKey,
                                    [NSNumber numberWithInt:kAudioFormatLinearPCM],
                                    AVFormatIDKey,
                                    [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
                                    nil];
    NSString *fileName = [NSString stringWithFormat:@"record_%@", [HOUtils getCurrentDateForFileName]];
    NSString *recorderFilePath = [HOUtils getFilePathWithFileName:fileName withFolderPath:[HOUtils getVoiceFolderPath] withExtension:FILE_TYPE_WAV];
    NSURL *url = [NSURL fileURLWithPath:recorderFilePath];
   // NSURL *url = [NSURL fileURLWithPath:[recorderFilePath stringByAppendingPathComponent:@"tmp.m4a"]];
    avRecorder = [[ HOAVAudioRecorder alloc] initWithURL:url settings:recordSettings error:&err];
    avRecorder.fileName = fileName;
    avRecorder.filePath = recorderFilePath;
    if(!avRecorder){
//        LogNor(@"recorder: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
        NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain
                                             code:[err code]
                                         userInfo:nil];
//        LogNor(@"Error: %@", [error description]);
        HOAlertView *alert =
        [[HOAlertView alloc] initWithTitle: @"警告"
                                   message: [error localizedDescription]
                                  delegate: nil
                         cancelButtonTitle:@"关闭"
						 otherButtonTitles:nil];
		alert.tag = [kHO_DIALOG_RecordWarning integerValue];
        [alert show];
		[alert release];
        return;
    }
    
    //prepare to record
    [avRecorder setDelegate:self];
    [avRecorder prepareToRecord];
    avRecorder.meteringEnabled = YES;

}
- (void)onRecordStopped:(BOOL)isRecordSuccessed
{
//    LogNor(@"avRecorder e:%@", avRecorder);
//    LogNor(@"isRecordSuccessed:%@" ,isRecordSuccessed?@"YES":@"NO");
    if(isRecordSuccessed)
    {
        
        AVURLAsset* audioAsset =[AVURLAsset URLAssetWithURL:avRecorder.url options:nil];
        
        CMTime audioDuration = audioAsset.duration;
        
        float audioDurationSeconds =CMTimeGetSeconds(audioDuration);
//        LogNor(@"audioDurationSeconds:%.1f", audioDurationSeconds);
        if(audioDurationSeconds < MIN_RECORDING_TIME)
        {
            [self stopTimer];
            isRecordLessOnSecTimeout = YES;
            [self startRecordTimer];
            [_delgate onRecordLessOneSecond:YES];
                      
        }
        else
        {
           
//            LogNor(@"avRecorder.filePath:%@", avRecorder.filePath);
//            LogNor(@"avRecorder.fileName:%@", avRecorder.fileName);
           // [self converttoamr:isRecordSuccessed withFilePath:avRecorder.filePath withFileName:avRecorder.fileName];
            [_delgate onStopRecord:isRecordSuccessed totalTime:audioDurationSeconds withFilePath:avRecorder.filePath withFileName:avRecorder.fileName];
        }
    }
    else
    {
       // [self converttoamr:isRecordSuccessed withFilePath:avRecorder.filePath withFileName:avRecorder.fileName];
        [_delgate onStopRecord:NO totalTime:recordTime withFilePath:avRecorder.filePath withFileName:avRecorder.fileName];
    }
}
-(void)converttoamr:(BOOL)isSuccessed withFilePath:(NSString *)filePath withFileName:(NSString *)fileName
{
//	NSString *recordFileName = [NSString stringWithFormat:@"%@.%@", fileName, FILE_TYPE_WAV];
//	NSString *recorderFilePath =
	NSString *recorderFilePath = [HOUtils getFilePathWithFileName:fileName withFolderPath:[HOUtils getVoiceFolderPath] withExtension:FILE_TYPE_WAV];
    if ([HOUtils isExistFileInLocal:recorderFilePath]) {
        return;
    }
   [VoiceConverter wavToAmr:filePath amrSavePath:recorderFilePath];
    avRecorder.wavfilePath = filePath;
    avRecorder.filePath = recorderFilePath;

}

- (void)destoryRecord:(BOOL)isRecordSuccessed
{
    if (isRecordSuccessed)
    {
    [self stopTimer];
   

    @try {
        
               // [session setActive:NO error:&err];
    }
    @catch (NSException *exception) {
        
    }
    @finally {
        
    }

  
    recordTime = 0;
    if(avRecorder != nil)
    {
        if (IS_LESSTHAN_IOS6) {
            
            avRecorder = nil;
        } else {
            avRecorder = nil;
        }
    }
    }
}
- (NSTimeInterval)getRecordingTime
{
    return recordTime;
}
- (void)resumeRecord
{
	if(recordStatus == RECORD_STOPPED)
		return;
    if(recordStatus == RECORD_STARTED)
        return;
    if(recordStatus == RECORD_PAUSED)
    {
        LogNor(@"re-record");
        if(!avRecorder.recording)
            [avRecorder record];
        [_delgate onResumeRecord];
    }
    recordStatus = RECORD_STARTED;
}
- (void)startRecord
{
    if(recordStatus == RECORD_STARTED)
        return;
  
    else if(recordStatus == RECORD_STOPPED)
    {
        
        LogNor(@"start");
        [self initRecord];
        //    kAudioFormatAppleIMA4

        [avRecorder record];
        isRecordLessOnSecTimeout = NO;
        [self startRecordTimer];
        [_delgate onStartRecord];
    }
    recordStatus = RECORD_STARTED;
}
- (void)pauseRecord
{
    
    if(recordStatus == RECORD_PAUSED)
        return;
    LogNor(@"pause");
    recordStatus = RECORD_PAUSED;
    if(avRecorder.isRecording)
    {
        [avRecorder pause];
    }
    [_delgate onPaused];
}
- (void)stopRecord
{
    LogNor(@"stop");
    if(recordStatus == RECORD_STOPPED)
        return;
    recordStatus = RECORD_STOPPED;
    [self stopTimer];
    if(avRecorder.isRecording)
    {
        [avRecorder stop];
        NSError *err = nil;
        session = [AVAudioSession sharedInstance];
//        int flags = AVAudioSessionSetActiveFlags_NotifyOthersOnDeactivation;
//        [session setActive:NO withFlags:flags error:&err];
		[session setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&err];
        
    }
    else
    {
        [self onRecordStopped:YES];
        [self destoryRecord:YES];
    }
}

#pragma mark - AVAudioRecorderDelegate mathods

- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag
{
    [self onRecordStopped:YES];
    
    recordTime = 0;
    if(avRecorder != nil)
    {
		avRecorder.delegate = nil;
        if (IS_LESSTHAN_IOS6) {
            
            avRecorder = nil;
        } else {
            avRecorder = nil;
        }
    }
    
    
}

/* if an error occurs while encoding it will be reported to the delegate. */
- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError *)error
{
    [self destoryRecord:NO];
}


/* audioRecorderBeginInterruption: is called when the audio session has been interrupted while the recorder was recording. The recorded file will be closed. */
- (void)audioRecorderBeginInterruption:(AVAudioRecorder *)recorder
{
    [self destoryRecord:NO];
}

/* audioRecorderEndInterruption:withOptions: is called when the audio session interruption has ended and this recorder had been interrupted while recording. */
/* Currently the only flag is AVAudioSessionInterruptionFlags_ShouldResume. */
- (void)audioRecorderEndInterruption:(AVAudioRecorder *)recorder withOptions:(NSUInteger)flags NS_AVAILABLE_IOS(6_0)
{
    [self destoryRecord:NO];
}

- (void)audioRecorderEndInterruption:(AVAudioRecorder *)recorder withFlags:(NSUInteger)flags NS_DEPRECATED_IOS(4_0, 6_0)
{
    [self destoryRecord:NO];
}

/* audioRecorderEndInterruption: is called when the preferred method, audioRecorderEndInterruption:withFlags:, is not implemented. */
- (void)audioRecorderEndInterruption:(AVAudioRecorder *)recorder NS_DEPRECATED_IOS(2_2, 6_0)
{
    [self destoryRecord:NO];
}

- (void)dealloc
{
	[avRecorder release];
	[super dealloc];
}


@end
